<template>
  <div>
    <div class="bpmnViewAll" :style="{ height: bpmnHeight }">
      <div class="bpmnBtn" v-if="xmlStr">
        <el-button type="primary" size="small" @click="zoomViewport(true)"
          ><el-icon><ZoomIn /></el-icon> 放大</el-button
        >
        <el-button type="warning" size="small" @click="zoomViewport(false)"
          ><el-icon><ZoomOut /></el-icon> 缩小</el-button
        >
        <el-button type="info" size="small" @click="fitViewport"
          ><el-icon><Aim /></el-icon> 适中</el-button
        >
      </div>
      <!-- bpmn 工作 -->
      <div class="view_cont" :class="!xmlStr ? 'view_cont_border' : ''" :style="{ height: bpmnHeight }">
        <div class="canvas" ref="canvasRef" id="canvas" v-show="xmlStr"></div>
      </div>
    </div>
  </div>
</template>
<script setup>
// 引入相关的依赖
import BpmnViewer from 'bpmn-js/lib/Viewer'
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll'
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'

import { reactive, ref, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ERR_OK } from 'config/statusCode'
import baseHeader from 'components/base-header'
import pageSelect from 'components/page-select'

const emit = defineEmits(['processesData'])
const router = useRouter()
const route = useRoute()
const canvasRef = ref(null)

const props = defineProps({
  xmlStr: {
    type: String,
    default() {
      return ''
    }
  },
  flowViewerList: {
    type: Array,
    default() {
      return ''
    }
  },
  flowViewMapId: {
    type: String,
    default() {
      return ''
    }
  },
  bpmnHeight: {
    type: String,
    default() {
      return ''
    }
  }
})

const bpmnViewerData = ref(null)
const canvas = ref(null)
const zoom = ref('')

const proData = () => {
  let processesData = bpmnViewerData.value.get('elementRegistry').get(props.flowViewMapId)?.businessObject?.$attrs

  for (const key in processesData) {
    if (key.indexOf('flowable:') === 0) {
      const newKey = key.replace('flowable:', '')
      processesData[newKey] = processesData[key]
      delete processesData[key]
    }
  }
  emit('processesData', processesData)
}
// 设置高亮颜色的
const fillColor = () => {
  proData()
  const canvas = bpmnViewerData.value.get('canvas')
  props.flowViewerList.forEach((item) => {
    bpmnViewerData.value.getDefinitions().rootElements[0].flowElements.forEach((n) => {
      if (item.key === n.id && item.completed) {
        canvas.addMarker(n.id, 'highlight')
        n.outgoing?.forEach((nn) => {
          const targetTask = props.flowViewerList.find((m) => m.key === nn.targetRef.id)
          if (targetTask) {
            canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
            canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
          }
        })
      } else if (item.key === n.id && !item.completed) {
        canvas.addMarker(n.id, 'highlight-todo')
      }
    })
  })
}
// 让图能自适应屏幕
const fitViewport = () => {
  zoom.value = bpmnViewerData.value.get('canvas').zoom('fit-viewport', 'auto')
}
const initDiagram = async () => {
  try {
    const result = await bpmnViewerData.value.importXML(props.xmlStr)
    const { warnings } = result
    const canvas = bpmnViewerData.value.get('canvas')
    canvas.zoom('fit-viewport', true)
    if (props.flowViewerList !== undefined && props.flowViewerList.length > 0) {
      fillColor()
    }
  } catch (err) {}
}
const init = () => {
  // 创建Bpmn对象
  bpmnViewerData.value = new BpmnViewer({
    container: canvasRef.value,
    additionalModules: [ZoomScrollModule, MoveCanvasModule]
  })

  initDiagram()
}

// 放大缩小
const zoomViewport = (zoomIn = true) => {
  zoom.value = bpmnViewerData.value.get('canvas').zoom()
  zoom.value += zoomIn ? 0.1 : -0.1
  if (zoom.value >= 0.2) bpmnViewerData.value.get('canvas').zoom(zoom.value)
}

onMounted(() => {
  if (props.xmlStr) init()
})
</script>

<style lang="scss" scoped>
.bpmnViewAll {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  overflow: hidden;
  height: calc(80vh - 130px);
}
.view_cont {
  width: 100%;
  height: calc(80vh - 130px);
  flex: 1;
  position: relative;
  border-bottom: 1px solid #e5e5e5;
  background: url()
    repeat !important;
}
.view_cont_border {
  border-right: 1px solid #e5e5e5;
}

.bpmnBtn {
  width: 100%;
  display: inline-block;
  margin-bottom: 10px;
}

:deep(.highlight.djs-shape .djs-visual > :nth-child(1)) {
  fill: #53ba1c !important;
  stroke: #53ba1c !important;
  fill-opacity: 0.2 !important;
}
:deep(.highlight.djs-shape .djs-visual > :nth-child(2)) {
  fill: #53ba1c !important;
}
:deep(.highlight.djs-shape .djs-visual > path) {
  fill: #53ba1c !important;
  fill-opacity: 0.2 !important;
  stroke: #53ba1c !important;
}
:deep(.highlight.djs-connection > .djs-visual > path) {
  stroke: #53ba1c !important;
}
:deep(.highlight-todo.djs-connection > .djs-visual > path) {
  stroke: #ff8d20 !important;
  stroke-dasharray: 4px !important;
  fill-opacity: 0.2 !important;
}
:deep(.highlight-todo.djs-shape .djs-visual > :nth-child(1)) {
  fill: #ff8d20 !important;
  stroke: #ff8d20 !important;
  stroke-dasharray: 4px !important;
  fill-opacity: 0.2 !important;
}
:deep(.overlays-div) {
  font-size: 10px;
  color: red;
  width: 100px;
  top: -20px !important;
}
.canvas {
  width: 100%;
  height: 100%;
}
</style>
